package com.daodao.daodaoschedule.infrastructure.util;

import com.daodao.daodaoschedule.infrastructure.util.converters.LocalDateConverter;
import com.daodao.daodaoschedule.infrastructure.util.converters.LocalDateTimeConverter;
import com.daodao.daodaoschedule.infrastructure.util.converters.StringBooleanConverter;
import com.google.common.collect.Maps;
import ma.glasnost.orika.MapperFacade;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;
import org.springframework.cglib.beans.BeanMap;

import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * @author mal
 * @date 2023-02-14 17:02
 */
public class BeanCopyUtils {
    private static final MapperFactory MAPPER_FACTORY = new DefaultMapperFactory.Builder().build();

    private static final MapperFacade MAPPER_FACADE = MAPPER_FACTORY.getMapperFacade();


    static {
        MAPPER_FACTORY.getConverterFactory().registerConverter(new StringBooleanConverter());
        MAPPER_FACTORY.getConverterFactory().registerConverter(new LocalDateConverter());
        MAPPER_FACTORY.getConverterFactory().registerConverter(new LocalDateTimeConverter());

    }

    private BeanCopyUtils() {

    }

    public static <T> Map<String, Object> beanToMap(T bean) {
        Map<String, Object> map = Maps.newHashMap();
        if (bean != null) {
            BeanMap beanMap = BeanMap.create(bean);
            for (Object key : beanMap.keySet()) {
                map.put(key.toString(), beanMap.get(key));
            }
        }
        return map;

    }

    public static <T> T mapToBean(Map<String, Object> map, T bean) {
        BeanMap beanMap = BeanMap.create(bean);
        beanMap.putAll(map);
        return bean;
    }

    public static <T> T copyBean(Object source, T target) {
        if (source == null) {
            return null;
        }
        MAPPER_FACADE.map(source, target);
        return target;
    }


    public static <T> T copyBean(Object source, Class<T> targetClass) {
        if (source == null) {
            return null;
        }
        return MAPPER_FACADE.map(source, targetClass);
    }


    public static <S, D> List<D> mapAsList(Collection<S> source, Class<D> targetClass) {
        return MAPPER_FACADE.mapAsList(source, targetClass);
    }

    public static MapperFactory getMapperFactory() {
        return MAPPER_FACTORY;
    }


}
